package com.zj;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/*
* 线程池的任务分配及调度，结果汇总
* */
public class BestMatchingConcurrentCalculation {
    /**
     * 并发计算最佳匹配数据
     * @param word 目标单词
     * @param dictionary 单词列表
     * @return 最佳匹配数据
     */
    public  static BestMatchingData getBestMatchingData(String word, List<String> dictionary) throws ExecutionException, InterruptedException {
        BestMatchingData result=new BestMatchingData();
        //1.任务数
        int numCores=Runtime.getRuntime().availableProcessors();//获取CPU核心数
        ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);

       //另一个线程方案  使用CountDownLatch  等待所有的任务执行完毕
        CountDownLatch latch=new CountDownLatch(numCores);

        //2.计算每个任务对应的词汇量 startIndex endIndex
        int size=dictionary.size();
        int step=size/numCores;  //分区大小  ,每个任务多少个
        int startIndex,endIndex;

        //3.创建 BestMatchingTask
        List<BestMatchingTask> tasks=new ArrayList<>();

//        List<Future<BestMatchingData>> listFutures=new ArrayList<>();
        for (int i = 0; i < numCores; i++) {
            startIndex=i*step;
            //endIndex
            if (i==numCores-1){
                endIndex=size-1;
            }else {
                endIndex=(i+1)*step-1;
            }
            BestMatchingTask task=new BestMatchingTask(word,dictionary,startIndex,endIndex);
            BestMatchingTask task1=new BestMatchingTask(word,dictionary,startIndex,endIndex,latch);
            tasks.add(task);

            Future<BestMatchingData> future= executor.submit(task1);
//            listFutures.add(future);
        }

        //4.将上面创建的BestMatchingTask 提交给线程池运行
        //集体提交任务  invokeAll一次性提交任务后，只有所有的任务全部执行完毕，才会向下运行
        //换句话说，程序会阻塞此处
        List<Future<BestMatchingData>> listFutures=executor.invokeAll(tasks);  //一次性提交所有的任务

//        latch.await();
        //关闭线程池
        executor.shutdown();

        //5.通过 FutureTask.get() 方法获取每个任务的运行结果 BestMatchingData  汇总(找最小距离  及对应的词汇表)
        int minDistance=Integer.MAX_VALUE;
        List<String> words=new ArrayList<>();  //最短距离  对应的单词
        for (Future<BestMatchingData> future : listFutures) {
            BestMatchingData bestMatchingData = future.get();
            //寻找最短距离
            if (bestMatchingData.getDistance()<minDistance){
                words.clear();  //清空
                minDistance=bestMatchingData.getDistance();
                words.addAll(bestMatchingData.getWords());
            }else if (bestMatchingData.getDistance()==minDistance){
                //这个任务找到最短距离 与已知的一样，则合并单词列表
                words.addAll(bestMatchingData.getWords());
            }
        }

        //6.包装BestMatchingData
        result.setDistance(minDistance);
        result.setWords(words);
        return result;
    }
}
